package com.shi.aspect;

import com.shi.annotation.auth.MyAuth;
import com.shi.common.ResultCodeEnum;
import com.shi.enums.PermCodeEnum;
import com.shi.exception.BusinessException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;

@Aspect
@Component
@Order(-1)
public class AuthAspect {

    /**
     * 将常量放到 常量类中管理，因为在其他地方也需要用到
     */
    private static final String SESSION_LOGIN_USER_KEY = "session_login_user_key";

    @Pointcut("@annotation(com.shi.annotation.auth.MyAuth)")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void handle(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        MyAuth annotation = method.getAnnotation(MyAuth.class);
        // 不需要认证
        if (!annotation.requireAuth()) {
            return;
        }
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpSession session = request.getSession();
        // 检查是否登录
        checkLogin(session);
        // 不需要任何权限
        if (annotation.hasPerm() == PermCodeEnum.NO_NEED_PERM) {
            return;
        }
        checkPerm(session, annotation);
    }

    /**
     * 检查是否登录
     * 扩展：如果使用的token，请修改代码逻辑
     *
     * @param session
     */
    private void checkLogin(HttpSession session) {
        Object attribute = session.getAttribute(SESSION_LOGIN_USER_KEY);
        if (attribute == null) {
            throw new BusinessException(ResultCodeEnum.NO_LOGIN);
        }
    }

    private void checkPerm(HttpSession session, MyAuth annotation) {
        Object attribute = session.getAttribute(SESSION_LOGIN_USER_KEY);
        String code = annotation.hasPerm().getCode();
        // 将 attribute 强转为 session中的用户对象
        // 判断session对象中的 权限码中是否包含 要求的权限，不包含直接抛出异常
    }
}
